"""
Jimmy K. 
This algorithm uses a modified tit-for-tat strategy.
We cannot be 100% certain of whether or not an opponent hunted/slacked with us last round.
We can estimate the probability that an opponent hunted/slacked with us last round based on the reputations and earnings from last round.
We then hunt with this opponent with that probability.
Exceptions: Always hunt for first 2 rounds, Always slack if there is exactly 1 player left. 
"""

import random
class Player:
    def __init__(self):
        """
        Optional __init__ method is run once when your Player object is created before the
        game starts

        You can add other internal (instance) variables here at your discretion.

        You don't need to define food or reputation as instance variables, since the host
        will never use them. The host will keep track of your food and reputation for you
        as well, and return it through hunt_choices.
        """
        self.last_round_reputations = [0] # Opponent reputations from previous round
        self.last_round_opponent_hunt = [True] # Did opponent hunt with me last round? T/F
        self.total_decisions = 0 # Total number of hunt/slack decisions made
        self.EPS = 1e-8 # epsilon = 10^-8, used to avoid precision issues 

    # All the other functions are the same as with the non object oriented setting (but they
    # should be instance methods so don't forget to add 'self' as an extra first argument).

    def hunt_choices(self, round_number, current_food, current_reputation, m, player_reputations):
        num_opponents = len(player_reputations)
        if round_number <= 2:
            hunt_decisions = ['h' for x in player_reputations] # Always hunt for the first 2 rounds
        elif num_opponents == 1:
            hunt_decisions = ['s'] # Slack if only one other player is left
        else:
            hunt_decisions = ['h' for x in player_reputations]
            # For the i-th opponent in this round
            for i in xrange(num_opponents):
                # Determine the i-th opponent's min and max possible reputation from last round
                R = player_reputations[i]
                R_prev_min = ((self.total_decisions + num_opponents)*R - num_opponents)/self.total_decisions - self.EPS
                R_prev_max = ((self.total_decisions + num_opponents)*R)/self.total_decisions + self.EPS
                h = 0.0
                s = 0.0
                # For the j-th opponent from last round
                for j in xrange(len(self.last_round_reputations)):
                    # If the j-th opponent's reputation is in the range [R_prev_min,R_prev_max]
                    if R_prev_min <= self.last_round_reputations[j] <= R_prev_max:
                        if self.last_round_opponent_hunt[j]:
                            h += 1 # Increment h if j-th opponent hunted with me
                        else:
                            s += 1 # Increment s if j-th opponent slacked with me
                # The i-th opponent could be one of h+s opponents from last round
                # Of these h+s opponents, h hunted with me while s slacked with me
                # Hunt with the i-th opponent with probability h/(h+s), Slack with probability s/(h+s)            
                if random.random() > (h + self.EPS)/(h+s + 2*self.EPS):
                    hunt_decisions[i] = 's'
        # Update total number of hunt/slack decisions made and player's reputations        
        self.total_decisions += num_opponents        
        self.last_round_reputations = player_reputations
        return hunt_decisions

    def hunt_outcomes(self, food_earnings):
        # True if opponent hunted with me, False if opponent slacked with me
        self.last_round_opponent_hunt = map((lambda x: x>=0),food_earnings)

    def round_end(self, award, m, number_hunters):
        pass # do nothing
